package com.camel.chart.utils;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import com.camel.chart.MainApplication;
import com.camel.chart.enums.MsgTypeEnum;
import com.camel.chart.func.TcpClient;
import com.camel.chart.func.TcpServer;
import com.camel.chart.func.UdpClient;
import com.camel.chart.utils.entity.ApplicationConfig;
import com.camel.chart.utils.entity.CommonConstants;
import com.camel.chart.utils.entity.Msg;
import javafx.application.Platform;
import javafx.collections.ObservableList;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Node;
import javafx.scene.control.Button;
import javafx.scene.control.Control;
import javafx.scene.control.Label;
import javafx.scene.control.ScrollPane;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.*;
import javafx.scene.paint.Color;
import javafx.scene.text.Font;
import javafx.scene.text.Text;

import java.io.File;
import java.io.IOException;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.ResourceBundle;

public class MsgUtil {

    private ResourceBundle resourceBundle;

    private volatile static MsgUtil instance;


    public static synchronized MsgUtil getInstance() {
        if (instance == null) {
            synchronized (MsgUtil.class) {
                if (instance == null) {
                    instance = new MsgUtil();
                }
                instance.resourceBundle = MainApplication.getFXMLLoader().getResources();
            }
        }
        return instance;
    }

    public void send(Msg params, Control control) {
        try {
            new Thread(new UdpClient(new DatagramSocket(), 8888, InetAddress.getByAddress(ApplicationConfig.getInstance().getChartNetWorkInterface().getBroadCastAddressAsByteArray()), params, control)).start();
        } catch (SocketException e) {
            throw new RuntimeException(e);
        } catch (UnknownHostException e) {
            throw new RuntimeException(e);
        }
    }

    public void sendMsg(Object msg, MsgTypeEnum type, Control control) {
        Msg params = new Msg();
        params.setMsg(msg);
        params.setType(type);
        try {
            new Thread(new UdpClient(new DatagramSocket(), 8888,
                    InetAddress.getByAddress(IPUtils.getInetAddressByteArray(ApplicationConfig.getInstance().getCurrentDevice().getInetAddress())),
                    params, control)).start();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void sendTextMsg(String msg, Control control) {
        this.sendMsg(msg, MsgTypeEnum.TYPE_TEXT_MSG, control);
    }

    public void sendFileReqMsg(FileUtil.FileEntity fileEntity, Control control) {
        this.sendMsg(fileEntity, MsgTypeEnum.TYPE_FILE_REQ, control);
    }

    public void sendFileAckMsg(Msg msg, Control control) {
        this.sendMsg(msg.getMsg(), MsgTypeEnum.TYPE_FILE_ACK, control);
        this.updateMsgUI((ScrollPane) control, msg, true);
    }

    public void sendFileMsg(FileUtil.FileEntity fileEntity, Control control) {
        this.sendMsg(fileEntity, MsgTypeEnum.TYPE_FILE_MSG, control);
    }


    public HBox createMsgDateUI(Msg msg) {
        return createMsgDateUI(msg, msg.isLeft());
    }

    public HBox createMsgDateUI(Msg msg, boolean isLeft) {
        if (msg.getType().equals(MsgTypeEnum.TYPE_TEXT_MSG)) {
            return createTextUI(msg.getDataTime(), isLeft, 1220, 12, Color.GREY, msg);
        }
        if (msg.getType().equals(MsgTypeEnum.TYPE_FILE_REQ)) {
            FileUtil.FileEntity f = (FileUtil.FileEntity) msg.getMsg();
            return createTextUI(msg.getDataTime(), isLeft, 1220, 12, Color.GREY, msg);
        }
        return null;
    }

    public HBox createMsgDetailUI(Msg msg) {
        return createMsgDetailUI(msg, msg.isLeft());
    }

    public HBox createMsgDetailUI(Msg msg, boolean isLeft) {
        if (msg.getType().equals(MsgTypeEnum.TYPE_TEXT_MSG)) {
            return createTextUI(msg.getMsg().toString(), isLeft, 1220, 20, null, msg);
        }
        if (msg.getType().equals(MsgTypeEnum.TYPE_FILE_REQ)) {
            FileUtil.FileEntity f = (FileUtil.FileEntity) msg.getMsg();
            return this.createFileReqUI(f.getFileName(), isLeft, 20, null, msg);
        }
        return null;
    }

    public HBox createTextUI(String str, boolean isLeft, double preWidth, double fontSize, Color color, Msg msg) {
        HBox pane = new HBox();
        pane.setPadding(new Insets(0, 20, 0, 0));
        pane.setMinWidth(preWidth);
        pane.setMaxWidth(preWidth);
        if (!isLeft) {
            pane.setAlignment(Pos.BASELINE_RIGHT);
        }
        Text userInfo = new Text();
        userInfo.setText(str);
        userInfo.setY(60);
        userInfo.setFont(new Font(fontSize));
        if (!ObjectUtil.isEmpty(color)) {
            userInfo.setFill(color);
        }
        pane.getChildren().add(userInfo);
        return pane;
    }

    public HBox createFileReqUI(String str, boolean isLeft, double fontSize, Color color, Msg msg) {
        HBox hBox = new HBox();
        FileUtil.FileEntity f = (FileUtil.FileEntity) msg.getMsg();
        hBox.setId(f.getFileId());
        hBox.getProperties().put("isLeft", isLeft);
        hBox.setPadding(new Insets(0, 20, 0, 0));
        if (!isLeft) {
            hBox.setAlignment(Pos.BASELINE_RIGHT);
        }

        Text msgText = new Text();
        msgText.setText(str);
        msgText.setY(20);
        msgText.setX(20);
        msgText.setFont(new Font(fontSize));
        if (!ObjectUtil.isEmpty(color)) {
            msgText.setFill(color);
        }

        Pane pane = new Pane();
        File file = new File("D:\\IamFxFiles\\" + f.getFileName());

        double textWidth = msgText.getLayoutBounds().getWidth() + 40;
        pane.setPrefWidth(Math.max(textWidth, 200.0));
        pane.setBackground(new Background(new BackgroundFill(Color.GRAY, CornerRadii.EMPTY, Insets.EMPTY)));
        pane.setStyle("-fx-padding: 5; -fx-background-color: rgba(224,223,223,0.76); -fx-background-radius: 10;");
        pane.setPadding(new Insets(20, 20, 20, 20));
        pane.getChildren().add(msgText);
        pane.getProperties().put("type", "fileReq");
        pane.setId("fileReq" + f.getFileId());
        if (isLeft) {
            if(!file.exists()) {
                Button y = new Button();
                y.setText(resourceBundle.getString("Agree"));
                y.setLayoutY(60);
                y.setLayoutX(textWidth / 4 - 30);

                Button n = new Button();
                n.setText(resourceBundle.getString("Reject"));
                n.setLayoutY(60);
                n.setLayoutX(textWidth * 0.75 - 30);

                y.setOnMouseClicked(event -> {
                    MsgUtil.getInstance().sendFileAckMsg(msg, ApplicationConfig.getInstance().getApplication().chartContent);
                });
                n.setOnMouseClicked(event -> System.out.println("点击N"));
                pane.getChildren().add(y);
                pane.getChildren().add(n);
            } else {
                Label label = new Label("下载完成");
                label.getProperties().put("fielId", f.getFileId());
                label.setLayoutX(30);
                label.setLayoutY(50);
                double paneWidth = pane.getPrefWidth();
                Label openFileLabel = new Label("打开文件");
                openFileLabel.setLayoutX(paneWidth / 2);
                openFileLabel.setLayoutY(50);
                openFileLabel.setTextFill(Color.BLUE);

                // 点击打开文件夹
                openFileLabel.setOnMouseClicked(event -> {
                    String command = null;

                    if (System.getProperty("os.name").startsWith("Windows")) {
                        String s = "D:\\IamFxFiles\\" + f.getFileName();
                        command = "explorer /e,/select, " + s;
                    } else {
//                                                command = "open -R " + filePath;
                    }
                    try {
                        Runtime.getRuntime().exec(command);
                    } catch (IOException e) {
                        throw new RuntimeException(e);
                    }
                });


                pane.getChildren().add(label);
                pane.getChildren().add(openFileLabel);
            }

        } else {
            Label label = new Label("等待对方同意");
            label.setLayoutX(50);
            label.setLayoutY(50);
            pane.getChildren().add(label);
        }
        hBox.getChildren().add(pane);

        return hBox;
    }

    public void addMsgUI(ScrollPane control, Msg msgEntity) {
        Platform.runLater(() -> {
            VBox v = new VBox();
            HBox dui = MsgUtil.getInstance().createMsgDateUI(msgEntity, msgEntity.isLeft());
            if (!ObjectUtil.isEmpty(dui)) {
                dui.setPadding(CommonConstants.TIME_INSETS);
                if (ObjectUtil.isEmpty(control.getContent())) {
                    v.getChildren().add(dui);
                    control.setContent(v);
                } else {
                    VBox box = (VBox) control.getContent();
                    box.getChildren().add(dui);
                }
            }

            HBox detailUI = MsgUtil.getInstance().createMsgDetailUI(msgEntity);
            if (!ObjectUtil.isEmpty(detailUI)) {
                detailUI.setPadding(CommonConstants.DATA_INSETS);
                if (ObjectUtil.isEmpty(control.getContent())) {
                    v.getChildren().add(detailUI);
                    control.setContent(v);
                } else {
                    VBox box = (VBox) control.getContent();
                    box.getChildren().add(detailUI);
                }
            }
        });
    }

    public void updateMsgUI(ScrollPane control, Msg msgEntity) {
        updateMsgUI(control, msgEntity, msgEntity.isLeft());
    }

    public void updateMsgUI(ScrollPane control, Msg msgEntity, boolean isLeft) {
        Platform.runLater(() -> {
            Object msg = msgEntity.getMsg();
            if (msg instanceof FileUtil.FileEntity) {
                FileUtil.FileEntity fileEntity = (FileUtil.FileEntity) msg;
                if (ObjectUtil.isEmpty(control.getContent())) {
                    return;
                } else {
                    VBox box = (VBox) control.getContent();
                    for (Node child : box.getChildren()) {
                        if (isLeft) {
                            HBox hbox = (HBox) child;
                            if (CollectionUtil.isEmpty(hbox.getChildren())) {
                                return;
                            }
                            if (fileEntity.getFileId().equals(hbox.getId()) && ObjectUtil.isNotNull(hbox.getProperties().get("isLeft")) && hbox.getProperties().get("isLeft").equals(isLeft)) {
                                Pane pane = (Pane) hbox.getChildren().get(0);
                                ObservableList<Node> children = pane.getChildren();

                                Object o = pane.getProperties().get("type");
                                String id = pane.getId();
                                if (!ObjectUtil.isEmpty(o) && o.equals("fileReq") && ObjectUtil.isNotNull(id) && id.equals("fileReq" + fileEntity.getFileId())) {
                                    children.removeIf(item -> item instanceof Button);
                                    Label label = new Label("文件下载中");
                                    label.setId("textFileDownLoading" + fileEntity.getFileId());
                                    label.getProperties().put("fielId", fileEntity.getFileId());
                                    label.setLayoutX(30);
                                    label.setLayoutY(50);
                                    pane.setId("fileDownload" + fileEntity.getFileId());
                                    pane.getProperties().put("type", "fileDownload");
                                    pane.getChildren().add(label);
                                    hbox.setId(fileEntity.getFileId());
                                }
                                if (!ObjectUtil.isEmpty(o) && o.equals("fileDownload") && ObjectUtil.isNotNull(id) && id.equals("fileDownload" + fileEntity.getFileId())) {
                                    children.removeIf(item -> item instanceof Label);
                                    Label label = new Label("文件下载完成");
                                    label.getProperties().put("fielId", fileEntity.getFileId());
                                    label.setLayoutX(0);
                                    label.setLayoutY(50);
                                    hbox.setId(fileEntity.getFileId());
                                    double paneWidth = pane.getWidth();
                                    Label openFileLabel = new Label("打开文件");
                                    openFileLabel.setLayoutX(paneWidth / 2);
                                    openFileLabel.setLayoutY(50);
                                    openFileLabel.setTextFill(Color.BLUE);

                                    // 点击打开文件夹
                                    openFileLabel.setOnMouseClicked(new EventHandler<MouseEvent>() {
                                        @Override
                                        public void handle(MouseEvent event) {
                                            String command = null;

                                            if (System.getProperty("os.name").startsWith("Windows")) {
                                                command = "explorer /select, " + TcpServer.filePath + "//" + fileEntity.getFileName();
                                            } else {
//                                                command = "open -R " + filePath;
                                            }
                                            try {
                                                Runtime.getRuntime().exec(command);
                                            } catch (IOException e) {
                                                throw new RuntimeException(e);
                                            }
                                        }
                                    });

                                    pane.setId("fileDownload" + fileEntity.getFileId());
                                    pane.getProperties().put("type", "fileDownload");
                                    pane.getChildren().add(label);
                                    pane.getChildren().add(openFileLabel);
                                }

                            }

                        } else {
                            HBox hbox = (HBox) child;
                            if (CollectionUtil.isEmpty(hbox.getChildren())) {
                                return;
                            }
                            if (fileEntity.getFileId().equals(hbox.getId()) && ObjectUtil.isNotNull(hbox.getProperties().get("isLeft")) && hbox.getProperties().get("isLeft").equals(isLeft)) {
                                Pane pane = (Pane) hbox.getChildren().get(0);
                                ObservableList<Node> children = pane.getChildren();

                                children.removeIf(item -> item instanceof Label);
                                Label label = new Label("对方已接收");
                                label.setLayoutX(50);
                                label.setLayoutY(50);
                                pane.getChildren().add(label);
                            }
                        }

                    }

                }
            }

        });
    }

    public void updateMsgFileDownloadComplete(MainApplication application, Msg msgEntity) {
        ScrollPane control = application.chartContent;
        Platform.runLater(() -> {
            Object msg = msgEntity.getMsg();
            if (msg instanceof FileUtil.FileEntity) {
                FileUtil.FileEntity fileEntity = (FileUtil.FileEntity) msg;
                if (ObjectUtil.isEmpty(control.getContent())) {
                    return;
                } else {
                    VBox box = (VBox) control.getContent();
                    for (Node child : box.getChildren()) {
                        if (true) {
                            HBox hbox = (HBox) child;
                            if (CollectionUtil.isEmpty(hbox.getChildren())) {
                                return;
                            }
                            if (fileEntity.getFileId().equals(hbox.getId()) && ObjectUtil.isNotNull(hbox.getProperties().get("isLeft")) && hbox.getProperties().get("isLeft").equals(true)) {
                                Pane pane = (Pane) hbox.getChildren().get(0);
                                ObservableList<Node> children = pane.getChildren();

                                Object o = pane.getProperties().get("type");
                                String id = pane.getId();
                                children.removeIf(item -> item instanceof Button);
                                Label label = new Label("文件下载完成");
                                label.getProperties().put("fielId", fileEntity.getFileId());
                                label.setLayoutX(30);
                                label.setLayoutY(50);
                                hbox.setId(fileEntity.getFileId());
                                double paneWidth = pane.getWidth();
                                Label openFileLabel = new Label("打开文件");
                                openFileLabel.setLayoutX(paneWidth / 2);
                                openFileLabel.setLayoutY(50);
                                openFileLabel.setTextFill(Color.BLUE);

                                // 点击打开文件夹
                                openFileLabel.setOnMouseClicked(new EventHandler<MouseEvent>() {
                                    @Override
                                    public void handle(MouseEvent event) {
                                        String command = null;

                                        if (System.getProperty("os.name").startsWith("Windows")) {
                                            String s = "D:\\IamFxFiles\\" + fileEntity.getFileName();
                                            command = "explorer /e,/select, " + s;
                                        } else {
//                                                command = "open -R " + filePath;
                                        }
                                        try {
                                            Runtime.getRuntime().exec(command);
                                        } catch (IOException e) {
                                            throw new RuntimeException(e);
                                        }
                                    }
                                });

                                pane.setId("fileDownload" + fileEntity.getFileId());
                                pane.getProperties().put("type", "fileDownload");
                                pane.getChildren().add(label);
                                pane.getChildren().add(openFileLabel);
                            }

                        } else {
                            HBox hbox = (HBox) child;
                            if (CollectionUtil.isEmpty(hbox.getChildren())) {
                                return;
                            }
                            if (fileEntity.getFileId().equals(hbox.getId()) && ObjectUtil.isNotNull(hbox.getProperties().get("isLeft")) && hbox.getProperties().get("isLeft").equals(true)) {
                                Pane pane = (Pane) hbox.getChildren().get(0);
                                ObservableList<Node> children = pane.getChildren();

                                children.removeIf(item -> item instanceof Label);
                                Label label = new Label("对方已接收");
                                label.setLayoutX(50);
                                label.setLayoutY(50);
                                pane.getChildren().add(label);
                            }
                        }
                    }
                }
            }

        });
    }


    public void sendTcpMsg(String msg, MsgTypeEnum msgType, Control control) {
        Msg params = new Msg();
        params.setMsg(msg);
        params.setType(msgType);
        try {
            new Thread(new TcpClient(51818,
                    InetAddress.getByAddress(IPUtils.getInetAddressByteArray(ApplicationConfig.getInstance().getCurrentDevice().getInetAddress())),
                    params, control)).start();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void sendTcpMsg(byte[] data, Control control) {
        try {
            new Thread(new TcpClient(51818,
                    InetAddress.getByAddress(IPUtils.getInetAddressByteArray(ApplicationConfig.getInstance().getCurrentDevice().getInetAddress())),
                    data, control)).start();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void sendTcpMsg(Msg msg, Control control) {
        try {
            new Thread(new TcpClient(51818,
                    InetAddress.getByAddress(IPUtils.getInetAddressByteArray(ApplicationConfig.getInstance().getCurrentDevice().getInetAddress())),
                    msg, control)).start();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
